package com.pactera.madp.cp.service.sync.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pactera.madp.cp.api.entity.sync.SyncCustomInfoEntity;
import com.pactera.madp.cp.common.constant.Constants;
import com.pactera.madp.cp.common.util.sync.SyncUtils;
import com.pactera.madp.cp.config.SyncConfig;
import com.pactera.madp.cp.context.SyncStateContext;
import com.pactera.madp.cp.mapper.sync.SyncCustomInfoMapper;
import com.pactera.madp.cp.service.sync.SyncCustomInfoHisService;
import com.pactera.madp.cp.service.sync.SyncCustomInfoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.*;

@Slf4j
@Service
@RequiredArgsConstructor
public class SyncCustomInfoServiceImpl extends ServiceImpl<SyncCustomInfoMapper, SyncCustomInfoEntity> implements SyncCustomInfoService {

    private final SyncCustomInfoHisService syncCustomInfoHisService;
    private final SyncConfig syncConfig;
    private final SyncCustomInfoMapper syncCustomInfoMapper;

    // 设置存储阀值，每当数据量达到以下值时进行一次数据库保存
    // 该值需根据mysql的max_allowed_packet变量大小进行设置
    private final int PER_SAVE_COUNTS = 10000;

    @Override
    public void addYesterdayToHis() {
        //log.debug("客户信息：addYesterdayToHis");
        //String date = DateUtil.format(new Date(), Constants.DATE_FORMAT);
        //syncCustomInfoHisService.syncOneDay(date);
    }

    @Override
    public void deleteYesterday() {
    }

    @Override
    public void parse() {
        log.debug("客户信息：parse");
        String filepath = SyncUtils.buildFilePath(syncConfig.getCrmPath(), Constants.FN_CUSTOM, SyncStateContext.get().getFileDate());
        File newestFile = SyncUtils.getNewestFile(filepath);

        List<String> lines = new ArrayList<>();

        int perCounts = syncConfig.getCrmPerCounts() == null ? PER_SAVE_COUNTS : syncConfig.getCrmPerCounts();

        Object[] tempData = SyncStateContext.get().getTempData();
        long n = (long) tempData[1];

        // 文件为Windows格式补2个字符，Unix格式补1个字符
        int fillChar = 1;
        List result = SyncUtils.segmentReadFile(newestFile, syncConfig.getCrmCharset(), n, fillChar, perCounts, lines);
        tempData[0] = result.get(0);
        tempData[1] = result.get(1);

        int counts = doBatchSaveOrUpdate(lines);

        int totalCount = (int) tempData[2] + counts;
        tempData[2] = totalCount;
        log.info("已同步CRM客户数据量：{}, 已读文件字符数：{}", totalCount, tempData[1]);
    }

    @Override
    public void deleteHisOneDay() {
        //log.debug("客户信息：deleteHisOneDay");
    }

    @Override
    public void syncBusiness() {
        log.debug("客户信息：syncBusiness");

        // 设置执行最终状态
        Object[] tempData = SyncStateContext.get().getTempData();
        boolean isContinue = (boolean) tempData[0];
        if (isContinue) {
            SyncStateContext.get().setFinalState(false);
        } else {
            SyncStateContext.get().setFinalState(true);
        }
    }

    /**
     * 存储更新数据
     * @param lines
     */
    private int doBatchSaveOrUpdate(List<String> lines) {
        List<SyncCustomInfoEntity> entityList = SyncUtils.crmParse(lines, Constants.SEPARATOR_VERTICAL_LINE, SyncCustomInfoEntity.class);
        Map<String, List<SyncCustomInfoEntity>> data = specialHandle(entityList);
        if (ObjectUtil.isNull(data)) {
            return 0;
        }
        data.forEach((k, v) -> {
            try {
                syncCustomInfoMapper.batchSaveOrUpdate(k, v);
            } catch (Exception e) {
                for (SyncCustomInfoEntity c : v) {
                    log.error("batch entity details：{}", JSONUtil.toJsonStr(c));
                }
                throw new RuntimeException(e);
            }
        });
        SyncStateContext.get().getTempData()[3] = entityList;
        return entityList.size();
    }

    /**
     * 分表存储
     * @param entityList
     * @return
     */
    private Map<String, List<SyncCustomInfoEntity>> specialHandle(List<SyncCustomInfoEntity> entityList) {
        if (CollUtil.isEmpty(entityList)) {
            return null;
        }
        Map<String, List<SyncCustomInfoEntity>> data = new HashMap<>();
        entityList.forEach(e -> {
            if (StrUtil.isEmpty(e.getCustNo())) {
                log.error("核心客户号不存在：{}", JSONUtil.toJsonStr(e));
                return;
            }
            String tableName = SyncUtils.getTableName(e.getCustNo(), Constants.TP_SYNC_CUSTOM_INFO, Constants.TC_CUSTOM_INFO);
            List<SyncCustomInfoEntity> list = data.get(tableName);
            if (ObjectUtil.isNull(list)) {
                list = new ArrayList<>();
                list.add(e);
                data.put(tableName, list);
            } else {
                list.add(e);
            }
        });
        return data;
    }

}
